package com.ruoyi.web.controller.exam.service;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONObject;
import com.egdk.api.entity.*;
import com.egdk.api.mapp.*;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.BeanMapper;
import com.ruoyi.common.utils.CronUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.SnowflakeIdWorker;
import com.ruoyi.exam.domain.PAnswer;
import com.ruoyi.exam.domain.PExam;
import com.ruoyi.exam.domain.PExamQuestion;
import com.ruoyi.exam.domain.PQuestion;
import com.ruoyi.exam.mapper.PAnswerMapper;
import com.ruoyi.exam.mapper.PExamQuestionMapper;
import com.ruoyi.exam.mapper.PQuestionMapper;
import com.ruoyi.quartz.job.enums.JobPrefix;
import com.ruoyi.quartz.job.service.JobService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.web.controller.exam.dto.*;
import com.ruoyi.web.controller.exam.enums.ExamState;
import com.ruoyi.web.controller.exam.enums.PaperState;
import com.ruoyi.web.controller.exam.enums.QuType;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.exam.mapper.PExamMapper;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;

@Service
public class StudentExamRestService {


    @Autowired
    private ElPaperMapper elPaperMapper;

    @Autowired
    private ElPaperQuMapper elPaperQuMapper;

    @Autowired
    private ElPaperQuAnswerMapper elPaperQuAnswerMapper;

    @Autowired
    private PExamMapper pExamMapper;

    @Autowired
    private PExamQuestionMapper pExamQuestionMapper;
    @Autowired
    private ISysUserService sysUserService;
    private final SnowflakeIdWorker idWorker = new SnowflakeIdWorker(1, 1);

    @Autowired
    private PAnswerMapper pAnswerMapper;

    @Autowired
    private JobService jobService;

    @Autowired
    private PQuestionMapper questionMapper;

    @Autowired
    private ElPaperService paperService;

    @Autowired
    private ElUserExamMapper userExamMapper;

    @Autowired
    private ElUserBookMapper userBookMapper;

    private static List<String> ABC = Arrays.asList(new String[]{
            "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X"
            , "Y", "Z"
    });

    @Transactional
    public String createPaper(Long userId, String examId) {
        ElPaperExample elPaperExample = new ElPaperExample();
        elPaperExample.createCriteria().andUserIdEqualTo(userId + "").andStateEqualTo(PaperState.ING);
        List<ElPaper> papers = elPaperMapper.selectByExample(elPaperExample);
        if (CollUtil.isNotEmpty(papers)) {
            throw new ServiceException("您有正在进行的考试！");
        }
        PExam exam = pExamMapper.selectPExamById(Long.valueOf(examId));
        if (exam == null) {
            throw new ServiceException("考试不存在！");
        }
        // 考试题目列表
        List<ElPaperQu> quList = this.generateByRepo(examId);

        if (CollectionUtils.isEmpty(quList)) {
            throw new ServiceException("数据库中无对应的考题，请尝试其它！");
        }
        //保存试卷内容
        ElPaper paper = this.savePaper(userId + "", exam, quList);
        // 强制交卷任务
        String jobName = JobPrefix.BREAK_EXAM + paper.getId();
        jobService.addCronJob(BreakExamJob.class, jobName, CronUtils.dateToCron(paper.getLimitTime()), paper.getId());

        return paper.getId();
    }

    /**
     * 自由组题方式产生题目列表
     *
     * @param examId
     * @return
     */
    private List<ElPaperQu> generateByRepo(String examId) {
        //最终的题目列表
        List<ElPaperQu> quList = new ArrayList<>();
        PExamQuestion pExamQuestion = pExamQuestionMapper.selectPExamQuestionByExamId(Long.valueOf(examId));
        if (pExamQuestion == null) {
            return quList;
        }
        String questionIds = pExamQuestion.getQuestionIds();
        String questionList = pExamQuestion.getQuestionList();
        String scores = pExamQuestion.getScores();
        // 生成试题和对应分数的 Map
        Map<String, String> questionScoreMap = new HashMap<>();
        String[] questionArray = questionList.split(",");
        String[] scoreArray = scores.split(",");

        if (questionArray.length == scoreArray.length) {
            for (int i = 0; i < questionArray.length; i++) {
                questionScoreMap.put(questionArray[i], scoreArray[i]);
            }
        }

        String[] questionIdPairs = questionIds.split("&");
        for (String questionIdPair : questionIdPairs) {
            String[] parts = questionIdPair.split("@");
            if (parts.length == 2) {
                String questionType = parts[0];
                String[] questionIdsInType = parts[1].split(",");
                for (String questionId : questionIdsInType) {
                    // 从 Map 中获取分数
                    String score = questionScoreMap.get(questionId);
                    ElPaperQu paperQu = new ElPaperQu();
                    paperQu.setQuId(questionId);
                    paperQu.setAnswered(false);
                    paperQu.setIsRight(false);
                    paperQu.setQuType(Integer.valueOf(questionType));
                    paperQu.setScore(Integer.valueOf(score));
                    paperQu.setActualScore(Integer.valueOf(score));
                    quList.add(paperQu);
                }
            }
        }
        return quList;
    }

    private ElPaper savePaper(String userId, PExam exam, List<ElPaperQu> quList) {


        // 查找用户
        SysUser user = sysUserService.selectUserById(Long.valueOf(userId));

        //保存试卷基本信息
        ElPaper paper = new ElPaper();
        paper.setId(idWorker.nextId() + "");
        paper.setDepartId(user.getDeptId() + "");
        paper.setExamId(exam.getId() + "");
        paper.setTitle(exam.getExamName());
        paper.setTotalScore(exam.getTotalScore());
        paper.setTotalTime(Integer.valueOf(exam.getDuration()));
        paper.setUserScore(0);
        paper.setUserId(userId);
        paper.setCreateTime(new Date());
        paper.setUpdateTime(new Date());
        paper.setQualifyScore(exam.getPassScore());
        paper.setState(PaperState.ING);
        paper.setHasSaq(false);

        // 截止时间
        Calendar cl = Calendar.getInstance();
        cl.setTimeInMillis(System.currentTimeMillis());
        cl.add(Calendar.MINUTE, Integer.valueOf(exam.getDuration()));
        paper.setLimitTime(cl.getTime());

        elPaperMapper.insertSelective(paper);

        if (!CollectionUtils.isEmpty(quList)) {
            this.savePaperQu(paper.getId(), quList);
        }

        return paper;
    }


    private void savePaperQu(String paperId, List<ElPaperQu> quList) {

        List<ElPaperQu> batchQuList = new ArrayList<>();
        List<ElPaperQuAnswer> batchAnswerList = new ArrayList<>();

        int sort = 0;
        for (ElPaperQu item : quList) {

            item.setPaperId(paperId);
            item.setSort(sort);
            item.setId(idWorker.nextId() + "");

            PAnswer pAnswer = pAnswerMapper.getQuestionId(Long.valueOf(item.getQuId()));
            String allOptions[] = pAnswer.getAllOption().split(",");
            int ii = 0;
            for (int i = 0; i < allOptions.length; i++) {
                ElPaperQuAnswer paperQuAnswer = new ElPaperQuAnswer();
                paperQuAnswer.setId(UUID.randomUUID().toString());
                paperQuAnswer.setPaperId(paperId);
                paperQuAnswer.setAnswerId((i + 1) + "");
                paperQuAnswer.setQuId(item.getQuId());
                paperQuAnswer.setChecked(false);
                paperQuAnswer.setSort(ii);
                paperQuAnswer.setAbc(ABC.get(ii));
                paperQuAnswer.setIsRight(pAnswer.getTrueOption().contains(i + ""));
                ii++;
                batchAnswerList.add(paperQuAnswer);
            }
            batchQuList.add(item);
            sort++;
        }
        new Thread(() -> {
            //添加问题
            if (CollUtil.isNotEmpty(batchQuList)) {
                for (ElPaperQu elPaperQu : batchQuList) {
                    elPaperQuMapper.insertSelective(elPaperQu);
                }
            }

            //批量添加问题答案
            if (CollUtil.isNotEmpty(batchAnswerList)) {
                for (ElPaperQuAnswer elPaperQuAnswer : batchAnswerList) {
                    elPaperQuAnswerMapper.insertSelective(elPaperQuAnswer);
                }
            }
        }).start();

    }

    public ExamDetailRespDTO paperDetail(String id) {

        ExamDetailRespDTO respDTO = new ExamDetailRespDTO();

        // 试题基本信息
        ElPaper paper = elPaperMapper.selectByPrimaryKey(id);
        BeanMapper.copy(paper, respDTO);

        ElPaperQuExample example = new ElPaperQuExample();
        example.createCriteria().andPaperIdEqualTo(id);
        example.setOrderByClause("sort asc");

        List<ElPaperQu> paperQus = elPaperQuMapper.selectByExample(example);
        List<PaperQuDTO> list = BeanMapper.mapList(paperQus, PaperQuDTO.class);

        List<PaperQuDTO> radioList = new ArrayList<>();
        List<PaperQuDTO> multiList = new ArrayList<>();
        List<PaperQuDTO> judgeList = new ArrayList<>();
        for (PaperQuDTO item : list) {
            if (QuType.RADIO.equals(item.getQuType())) {
                radioList.add(item);
            }
            if (QuType.MULTI.equals(item.getQuType())) {
                multiList.add(item);
            }
            if (QuType.JUDGE.equals(item.getQuType())) {
                judgeList.add(item);
            }
        }

        respDTO.setRadioList(radioList);
        respDTO.setMultiList(multiList);
        respDTO.setJudgeList(judgeList);
        return respDTO;
    }

    public PaperQuDetailDTO findQuDetail(String paperId, String quId) {
        PaperQuDetailDTO respDTO = new PaperQuDetailDTO();
        // 问题
        PQuestion qu = questionMapper.selectPQuestionById(Long.valueOf(quId));

        PAnswer answer = pAnswerMapper.getQuestionId(Long.valueOf(quId));
        String contents[] = answer.getAllOption().split(",");

        ElPaperQuExample example = new ElPaperQuExample();
        example.createCriteria().andPaperIdEqualTo(paperId).andQuIdEqualTo(quId);
        List<ElPaperQu> paperQus = elPaperQuMapper.selectByExample(example);
        // 基本信息
        ElPaperQu paperQu = paperQus.get(0);
        BeanMapper.copy(paperQu, respDTO);
        respDTO.setContent(qu.getQuContent());
        respDTO.setImage(qu.getImage());

        // 答案列表
        List<PaperQuAnswerExtDTO> list = elPaperQuAnswerMapper.listForExam(paperId, quId);
        if (CollUtil.isNotEmpty(list)) {
            for (int i = 0; i < list.size(); i++) {
                PaperQuAnswerExtDTO dto = list.get(i);
                dto.setContent(contents[Integer.valueOf(dto.getAnswerId()) - 1]);
            }
        }
        respDTO.setAnswerList(list);

        return respDTO;
    }

    public void fillAnswer(PaperAnswerDTO reqDTO) {
        // 未作答
        if (CollectionUtils.isEmpty(reqDTO.getAnswers())
                && StringUtils.isBlank(reqDTO.getAnswer())) {
            return;
        }

        ElPaperQuAnswerExample example = new ElPaperQuAnswerExample();
        example.createCriteria().andPaperIdEqualTo(reqDTO.getPaperId()).andQuIdEqualTo(reqDTO.getQuId());
        List<ElPaperQuAnswer> list = elPaperQuAnswerMapper.selectByExample(example);

        //查找答案列表
        //是否正确
        boolean right = true;
        //更新正确答案
        for (ElPaperQuAnswer item : list) {
            if (reqDTO.getAnswers().contains(item.getId())) {
                item.setChecked(true);
            } else {
                item.setChecked(false);
            }
            //有一个对不上就是错的
            if (item.getIsRight() != null && !item.getIsRight().equals(item.getChecked())) {
                right = false;
            }
            elPaperQuAnswerMapper.updateByPrimaryKeySelective(item);
        }

        //修改为已回答
        ElPaperQu qu = new ElPaperQu();
        qu.setQuId(reqDTO.getQuId());
        qu.setPaperId(reqDTO.getPaperId());
        qu.setIsRight(right);
        qu.setAnswer(reqDTO.getAnswer());
        qu.setAnswered(true);
        ElPaperQuExample elPaperQuExample = new ElPaperQuExample();
        elPaperQuExample.createCriteria().andPaperIdEqualTo(reqDTO.getPaperId()).andQuIdEqualTo(reqDTO.getQuId());
        elPaperQuMapper.updateByExampleSelective(qu, elPaperQuExample);
    }

    @Transactional(rollbackFor = Exception.class)
    public void handExam(String id) {
        paperService.handExam(id);
    }

    public ExamResultRespDTO paperResult(String paperId) {
        ExamResultRespDTO respDTO = new ExamResultRespDTO();

        // 试题基本信息
        ElPaper paper = elPaperMapper.selectByPrimaryKey(paperId);
        BeanMapper.copy(paper, respDTO);
        ElPaperQuExample example = new ElPaperQuExample();
        example.createCriteria().andPaperIdEqualTo(paperId);
        example.setOrderByClause("sort asc");

        List<ElPaperQu> quList = elPaperQuMapper.selectByExample(example);
        // 将 quList 转换为 paperQuDetailList
        List<PaperQuDetailDTO> paperQuDetailList = BeanMapper.mapList(quList, PaperQuDetailDTO.class);
        if (CollUtil.isNotEmpty(paperQuDetailList)) {
            for (PaperQuDetailDTO paperQuDetailDTO : paperQuDetailList) {
                //设置题目内容和图片
                PQuestion pQuestion = questionMapper.selectPQuestionById(Long.valueOf(paperQuDetailDTO.getQuId()));
                paperQuDetailDTO.setContent(pQuestion.getQuContent());
                paperQuDetailDTO.setImage(pQuestion.getImage());

                //用户的答案列表
                ElPaperQuAnswerExample quAnswerExample = new ElPaperQuAnswerExample();
                quAnswerExample.createCriteria().andQuIdEqualTo(paperQuDetailDTO.getQuId()).andPaperIdEqualTo(paperId);
                quAnswerExample.setOrderByClause("sort asc");
                List<ElPaperQuAnswer> quAnswerList = elPaperQuAnswerMapper.selectByExample(quAnswerExample);
                List<PaperQuAnswerExtDTO> paperQuAnswerExtList = BeanMapper.mapList(quAnswerList, PaperQuAnswerExtDTO.class);

                //真实答案
                PAnswer pAnswer = pAnswerMapper.getQuestionId(Long.valueOf(paperQuDetailDTO.getQuId()));
                String[] options = pAnswer.getAllOption().split(",");

                if (CollUtil.isNotEmpty(paperQuAnswerExtList)) {
                    for (int i = 0; i < paperQuAnswerExtList.size(); i++) {
                        PaperQuAnswerExtDTO paperQuAnswerExtDTO = paperQuAnswerExtList.get(i);
                        paperQuAnswerExtDTO.setContent(options[i]);

                        paperQuAnswerExtDTO.setIsRight(pAnswer.getTrueOption().contains(i + ""));
                    }
                }
                paperQuDetailDTO.setAnswerList(paperQuAnswerExtList);
            }
        }
        respDTO.setQuList(paperQuDetailList);
        return respDTO;
    }

    public AjaxResult myPaging(PagingReqDTO<UserExamReqDTO> reqDTO) {
        UserExamReqDTO params = reqDTO.getParams();
        if (params == null) {
            params = new UserExamReqDTO();
        }
        params.setUserId(SecurityUtils.getUserId() + "");

        //转换结果
        PageHelper.startPage(reqDTO.getCurrent(), reqDTO.getSize());
        List<UserExamRespDTO> pageData = userExamMapper.paging(reqDTO.getParams());
        PageInfo<UserExamRespDTO> pageInfo = new PageInfo<>(pageData);

        JSONObject object = new JSONObject();
        object.put("current", reqDTO.getCurrent());
        object.put("size", reqDTO.getSize());
        object.put("total", pageInfo.getTotal());
        object.put("pages", pageInfo.getPages());
        object.put("records", pageInfo.getList());

        return AjaxResult.success(object);
    }

    public AjaxResult paging(PagingReqDTO<GetMyExamDTO> reqDTO) {
        //转换结果
        PageHelper.startPage(reqDTO.getCurrent(), reqDTO.getSize());
        System.out.println(reqDTO.getParams() );
        List<PaperListRespDTO> pageData = userExamMapper.mypaging(reqDTO.getParams());
        PageInfo<PaperListRespDTO> pageInfo = new PageInfo<>(pageData);

        JSONObject object = new JSONObject();
        object.put("current", reqDTO.getCurrent());
        object.put("size", reqDTO.getSize());
        object.put("total", pageInfo.getTotal());
        object.put("pages", pageInfo.getPages());
        object.put("records", pageInfo.getList());

        return AjaxResult.success(object);
    }

    public AjaxResult wrongBookPaging(PagingReqDTO<UserBookDTO> reqDTO) {
        ElUserBookExample userBookExample = new ElUserBookExample();
        ElUserBookExample.Criteria criteria=userBookExample.createCriteria().andUserIdEqualTo(SecurityUtils.getUserId() + "");

        UserBookDTO params = reqDTO.getParams();
        if(params!=null){
            if(StringUtils.isNotEmpty(params.getTitle())){
                criteria.andTitleLike("%" + params.getTitle() + "%");
            }
            if(StringUtils.isNotEmpty(params.getExamId())){
                criteria.andExamIdEqualTo(params.getExamId());
            }
        }

        PageHelper.startPage(reqDTO.getCurrent(), reqDTO.getSize());
        List<ElUserBook> userBooks = userBookMapper.selectByExample(userBookExample);
        PageInfo<ElUserBook> pageInfo = new PageInfo<>(userBooks);
        JSONObject object = new JSONObject();
        object.put("current", reqDTO.getCurrent());
        object.put("size", reqDTO.getSize());
        object.put("total", pageInfo.getTotal());
        object.put("pages", pageInfo.getPages());
        object.put("records", pageInfo.getList());
        return AjaxResult.success(object);
    }

    public void removeByIds(List<String> ids) {
        if (CollUtil.isNotEmpty(ids)) {
            for (String id : ids) {
                userBookMapper.deleteByPrimaryKey(id);
            }
        }
    }

    public String findNext(String examId, String quId) {

        Integer sort = 999999;

        if(!org.springframework.util.StringUtils.isEmpty(quId)){
            ElUserBookExample example=new ElUserBookExample();
            example.createCriteria().andUserIdEqualTo(SecurityUtils.getUserId()+"").andExamIdEqualTo(examId).andQuIdEqualTo(quId);
            example.setOrderByClause("sort desc");
            List<ElUserBook> last = userBookMapper.selectByExample(example);
            if(CollUtil.isNotEmpty(last)){
                sort = last.get(0).getSort();
            }
        }

        ElUserBookExample example=new ElUserBookExample();
        example.createCriteria().andUserIdEqualTo(SecurityUtils.getUserId()+"").andExamIdEqualTo(examId).andSortLessThan(sort);
        example.setOrderByClause("sort desc");
        List<ElUserBook> next = userBookMapper.selectByExample(example);
        if(CollUtil.isNotEmpty(next)){
            return next.get(0).getQuId();
        }
        return null;
    }

    public QuDetailDTO qudetail(String id) {

        QuDetailDTO respDTO = new QuDetailDTO();
        PQuestion qu = questionMapper.selectPQuestionById(Long.valueOf(id));
        respDTO.setContent(qu.getQuContent());
        respDTO.setId(qu.getId()+"");
        respDTO.setCreateTime(qu.getCreateTime());
        respDTO.setImage(qu.getImage());
        respDTO.setLevel(Math.toIntExact(qu.getLevel()));
        respDTO.setQuType(Math.toIntExact(qu.getQuType()));


        PAnswer answer=pAnswerMapper.getQuestionId(Long.valueOf(id));
        String []opts=answer.getAllOption().split(",");

        List<QuAnswerDTO> answerList = new ArrayList<>();
        for (int i = 0; i < opts.length; i++) {
            QuAnswerDTO answerDTO=new QuAnswerDTO();
            answerDTO.setContent(opts[i]);
            answerDTO.setId((i+1)+"");
            answerDTO.setQuId(id);
            answerDTO.setIsRight(answer.getTrueOption().equals(i+""));
            answerList.add(answerDTO);
        }
        respDTO.setAnswerList(answerList);

        return respDTO;
    }
}
